package com.example.robertluozizhao.framecollectdemo.util;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * Created by fcz on 2017/9/11.
 */

public class ConvertUtils {
    private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    /**
     * 16进制数字字符集
     */
    private static String hexString = "0123456789ABCDEF";

    /**
     * long转数组 8位
     *
     * @param n
     * @return
     */
    public static byte[] longToBytes(long n) {
        byte[] b = new byte[8];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        b[4] = (byte) (n >> 32 & 0xff);
        b[5] = (byte) (n >> 40 & 0xff);
        b[6] = (byte) (n >> 48 & 0xff);
        b[7] = (byte) (n >> 56 & 0xff);
        return b;
    }

    /**
     * long转数组 8位
     *
     * @param n
     * @param array
     * @param offset
     */
    public static void longToBytes(long n, byte[] array, int offset) {
        array[0 + offset] = (byte) (n & 0xff);
        array[1 + offset] = (byte) (n >> 8 & 0xff);
        array[2 + offset] = (byte) (n >> 16 & 0xff);
        array[3 + offset] = (byte) (n >> 24 & 0xff);
        array[4 + offset] = (byte) (n >> 32 & 0xff);
        array[5 + offset] = (byte) (n >> 40 & 0xff);
        array[6 + offset] = (byte) (n >> 48 & 0xff);
        array[7 + offset] = (byte) (n >> 56 & 0xff);
    }

    /**
     * 数组转long 8位
     *
     * @param array
     * @return
     */
    public static long bytesToLong(byte[] array) {
        return ((((long) array[7] & 0xff) << 56)
                | (((long) array[6] & 0xff) << 48)
                | (((long) array[5] & 0xff) << 40)
                | (((long) array[4] & 0xff) << 32)
                | (((long) array[3] & 0xff) << 24)
                | (((long) array[2] & 0xff) << 16)
                | (((long) array[1] & 0xff) << 8)
                | (((long) array[0] & 0xff) << 0));
    }

    /**
     * 数组转long 8位
     *
     * @param array
     * @param offset
     * @return
     */
    public static long bytesToLong(byte[] array, int offset) {
        return ((((long) array[offset + 7] & 0xff) << 56)
                | (((long) array[offset + 6] & 0xff) << 48)
                | (((long) array[offset + 5] & 0xff) << 40)
                | (((long) array[offset + 4] & 0xff) << 32)
                | (((long) array[offset + 3] & 0xff) << 24)
                | (((long) array[offset + 2] & 0xff) << 16)
                | (((long) array[offset + 1] & 0xff) << 8)
                | (((long) array[offset + 0] & 0xff) << 0));
    }

    /**
     * int转数组
     * 将int转为低字节在前，高字节在后的byte数组
     * @param n int
     * @return byte[]
     *
     * @param n
     * @return
     */
    public static byte[] intToBytestoLH(int n) {
        byte[] b = new byte[4];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        return b;
    }
    /**
     * 将int转为高字节在前，低字节在后的byte数组
     * @param n int
     * @return byte[]
     */
    public static byte[] intToBytestoHH(int n) {
        byte[] b = new byte[4];
        b[3] = (byte) (n & 0xff);
        b[2] = (byte) (n >> 8 & 0xff);
        b[1] = (byte) (n >> 16 & 0xff);
        b[0] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * int转数组
     *
     * @param n
     * @param array
     * @param offset
     */
    public static void intToBytes(int n, byte[] array, int offset) {
        array[offset] = (byte) (n & 0xff);
        array[1 + offset] = (byte) (n >> 8 & 0xff);
        array[2 + offset] = (byte) (n >> 16 & 0xff);
        array[3 + offset] = (byte) (n >> 24 & 0xff);
    }

    /**
     * 数组转int
     *
     * @param b
     * @return
     */
    public static int bytesToInt(byte b[]) {
        return b[0] & 0xff
                | (b[1] & 0xff) << 8
                | (b[2] & 0xff) << 16
                | (b[3] & 0xff) << 24;
    }

    /**
     * 数组转int
     *
     * @param b
     * @return
     */
    public static int bytesToInt(byte b[], int offset) {
        return b[offset] & 0xff
                | (b[offset + 1] & 0xff) << 8
                | (b[offset + 2] & 0xff) << 16
                | (b[offset + 3] & 0xff) << 24;
    }

    /**
     * 数组转int
     * 将int转为高字节在前，低字节在后的byte数组 hh
     * @param b
     * @return
     */
    public static int bytesToIntHH(byte b[]) {
        return b[3] & 0xff
                | (b[2] & 0xff) << 8
                | (b[1] & 0xff) << 16
                | (b[0] & 0xff) << 24;
    }

    /**
     * 数组转int
     *将int转为高字节在前，低字节在后的byte数组 hh
     * @param b
     * @return
     */
    public static int bytesToIntHH(byte b[], int offset) {
        return b[offset+3] & 0xff
                | (b[offset + 2] & 0xff) << 8
                | (b[offset + 1] & 0xff) << 16
                | (b[offset + 0] & 0xff) << 24;
    }


    /**
     * long转数组 4位
     *
     * @return
     */
    public static byte[] uintToBytes(long n) {
        byte[] b = new byte[4];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * long转数组 4位
     *
     * @param n
     * @param array
     * @param offset
     */
    public static void uintToBytes(long n, byte[] array, int offset) {
        array[offset] = (byte) (n);
        array[1 + offset] = (byte) (n >> 8 & 0xff);
        array[2 + offset] = (byte) (n >> 16 & 0xff);
        array[3 + offset] = (byte) (n >> 24 & 0xff);
    }

    /**
     * 数组 转long 4位
     *
     * @param array
     * @return
     */
    public static long bytesToUint(byte[] array) {
        return ((long) (array[0] & 0xff))
                | ((long) (array[1] & 0xff)) << 8
                | ((long) (array[2] & 0xff)) << 16
                | ((long) (array[3] & 0xff)) << 24;
    }

    /**
     * 数组 转long 4位
     *
     * @param array
     * @param offset
     * @return
     */
    public static long bytesToUint(byte[] array, int offset) {
        return ((long) (array[offset + 0] & 0xff))
                | ((long) (array[offset + 1] & 0xff)) << 8
                | ((long) (array[offset + 2] & 0xff)) << 16
                | ((long) (array[offset + 3] & 0xff)) << 24;
    }

    /**
     * short转数组
     *
     * @param n
     * @return
     */
    public static byte[] shortToBytes(short n) {
        byte[] b = new byte[2];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) ((n >> 8) & 0xff);
        return b;
    }

    /**
     * short转数组
     *
     * @param n
     * @param array
     * @param offset
     */
    public static void shortToBytes(short n, byte[] array, int offset) {
        array[offset] = (byte) (n & 0xff);
        array[offset + 1] = (byte) ((n >> 8) & 0xff);
    }

    /**
     * 数组转short
     *
     * @param b
     * @return
     */
    public static short bytesToShort(byte[] b) {
        return (short) (b[0] & 0xff
                | (b[1] & 0xff) << 8);
    }

    /**
     * 数组转short
     *
     * @param b
     * @return
     */
    public static short bytesToShort(byte[] b, int offset) {
        return (short) (b[offset] & 0xff
                | (b[offset + 1] & 0xff) << 8);
    }

    public static byte[] ushortToBytes(int n) {
        byte[] b = new byte[2];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) ((n >> 8) & 0xff);
        return b;
    }

    public static void ushortToBytes(int n, byte[] array, int offset) {
        array[offset] = (byte) (n & 0xff);
        array[offset + 1] = (byte) ((n >> 8) & 0xff);
    }

    public static int bytesToUshort(byte b[]) {
        return b[0] & 0xff
                | (b[1] & 0xff) << 8;
    }

    public static int bytesToUshort(byte b[], int offset) {
        return b[offset] & 0xff
                | (b[offset + 1] & 0xff) << 8;
    }

    public static byte[] ubyteToBytes(int n) {
        byte[] b = new byte[1];
        b[0] = (byte) (n & 0xff);
        return b;
    }

    /**
     * 高位转低位
     *
     * @param n
     * @param array
     * @param offset
     */
    public static void ubyteToBytes(int n, byte[] array, int offset) {
        array[0] = (byte) (n & 0xff);
    }

    /**
     * 低位转高位
     *
     * @param array
     * @return
     */
    public static int bytesToUbyte(byte[] array) {
        return array[0] & 0xff;
    }

    /**
     * 低位转高位
     *
     * @param array
     * @return
     */
    public static int bytesToUbyte(byte[] array, int offset) {
        return array[offset] & 0xff;
    }


    /**
     * byte转String
     *
     * @param array
     * @param start
     * @param end
     * @return
     */
    public static String bytesToString(byte[] array, int start, int end) {
        String string = "";
        try {
            string = new String(Arrays.copyOfRange(array, start, end), "GB2312");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return string;
    }

    public static String bytes2HexString(byte[] array, int start, int end) {
        byte[] bytes = Arrays.copyOfRange(array, start, end);
        return bytes2HexString(bytes);
    }


    /**
     * 获取GB2312编码的byte数组
     *
     * @param string
     * @return
     */
    public static byte[] stringToBytes(String string) {
        try {
            return string.getBytes("GB2312");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }


//    // String 转char[]
    public static char[] getChars(String str) {
        char[] temp = new char[str.length()];
        temp = str.toCharArray();
        return temp;
    }



//-----------------------------------------------------以下是与串口的数据解析

    /**
     * byteArr转hexString
     * <p>例如：</p>
     * bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns 00A8
     *
     * @param bytes 字节数组
     * @return 16进制大写字符串
     */
    public static String bytes2HexString(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        int len = bytes.length;
        if (len <= 0) return null;
        char[] ret = new char[len << 1];
        for (int i = 0, j = 0; i < len; i++) {
            ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
            ret[j++] = hexDigits[bytes[i] & 0x0f];
        }
        return new String(ret);
    }

    /**
     * hexString转byteArr
     * <p>例如：</p>
     * hexString2Bytes("00A8") returns { 0, (byte) 0xA8 }
     *
     * @param hexString 十六进制字符串
     * @return 字节数组
     */
    public static byte[] hexString2Bytes(String hexString) {
        if ("".equals(hexString) || hexString == null) {
            return null;
        }
        int len = hexString.length();
        if (len % 2 != 0) {
            hexString = "0" + hexString;
            len = len + 1;
        }
        char[] hexBytes = hexString.toUpperCase().toCharArray();
        byte[] ret = new byte[len >> 1];
        for (int i = 0; i < len; i += 2) {
            ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1]));
        }
        return ret;
    }

    /**
     * hexChar转int
     *
     * @param hexChar hex单个字节
     * @return 0..15
     */
    private static int hex2Dec(char hexChar) {
        if (hexChar >= '0' && hexChar <= '9') {
            return hexChar - '0';
        } else if (hexChar >= 'A' && hexChar <= 'F') {
            return hexChar - 'A' + 10;
        } else {
            throw new IllegalArgumentException();
        }
    }


    /**
     * 16进制字符串转数字
     *
     * @param string
     * @return
     */
    public static int hexString2Int(String string) {
        return Integer.parseInt(string, 16);
    }

    /**
     * int转16进制byte
     *
     * @param integer
     * @return
     */
    public static byte[] int2HexByte(int integer) {
        return hexString2Bytes(Integer.toHexString(integer));
    }

    /**
     * 16进制字节数组转数字
     *
     * @return
     */
    public static int hexByte2Int(byte[] bytes) {
        return Integer.parseInt(bytes2HexString(bytes), 16);
    }



    /**
     * 将字符串编码成16进制数字,适用于所有字符（包括中文）
     */
    public static String encode(String str, String charset) throws UnsupportedEncodingException {
        //根据默认编码获取字节数组
        byte[] bytes = str.getBytes(charset);
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        //将字节数组中每个字节拆解成2位16进制整数
        for (int i = 0; i < bytes.length; i++) {
            sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
            sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
        }
        return sb.toString();
    }


    /**
     * 字符串转换成十六进制字符串
     */
    public static String str2HexStr(String str, String charset) throws UnsupportedEncodingException {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes(charset);
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString();
    }


    /**
     * 将16进制数字解码成字符串,适用于所有字符（包括中文）
     */
    public static String decode(String bytes, String charset) throws UnsupportedEncodingException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
        //将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray(), charset);
    }


    /**
     * 10进制转4长度的二进制（只用于输入口的判断）
     *
     * @param a
     * @return
     */
    public static String toBinaryForAlarmIn(int a) {
        String sr = "";
        String sc = "";
        int count = 0;        //二进制长度
        int b = Math.abs(a);
        while (b != 0) {
            sr = (b % 2) + sr;
            b = b / 2;
            count++;
        }
        if (a == 0) {
            for (int i = 0; i < 4 - count; i++) {  //4位的二进制
                sc += "0";
            }
            return sc;
        }
        if (a > 0) {
            for (int i = 0; i < 4 - count; i++) {  //4位的二进制
                sc += "0";
            }
            return sc + sr;
        } else {
            for (int i = 0; i < 4 - count; i++) {  //4位的二进制
                sc += "1";
            }
            for (int i = 0; i < sr.length(); i++) {    //取反
                if (sr.charAt(i) == '1') {
                    sc += '0';
                } else
                    sc += '1';
            }
            //加一
            int m = sc.length();        //记录原SC的长度
            for (int i = sc.length() - 1; i >= 0; i--) {
                if (sc.charAt(i) == '1') {
                    sc = sc.substring(0, i);
                    for (int j = 0; j < m - i; j++)
                        sc += '0';
                } else {
                    sc = sc.substring(0, i);
                    sc += '1';
                    for (int j = 0; j < m - i - 1; j++)
                        sc += '0';
                    break;
                }
            }
            return sc;
        }
    }

}
